<template>
  <div class="student-list">
    <div class="header">
      <h2>学生连接状态</h2>
      <button @click="fetchStudents" class="refresh-btn" :disabled="isLoading">
        <span v-if="!isLoading">刷新</span>
        <span v-else>刷新中...</span>
      </button>
    </div>

    <div v-if="error" class="error-message">
      {{ error }}
    </div>

    <div class="table-container" v-if="!isLoading">
      <table v-if="students.length > 0">
        <thead>
        <tr>
          <th>考号</th>
          <th>姓名</th>
          <th>IP地址</th>
          <th>注册时间</th>
          <th>最后心跳</th>
          <th>状态</th>
        </tr>
        </thead>
        <tbody>
        <tr v-for="student in sortedStudents" :key="student.machineId">
          <td>{{ student.examnumber || '-' }}</td>
          <td>{{ student.name || '-' }}</td>
          <td>{{ student.ipAddress || '-' }}</td>
          <td>{{ formatDate(student.registerTime) }}</td>
          <td>{{ formatDate(student.lastHeartbeat) }}</td>
          <td>
              <span :class="['status-badge', getStatusClass(student.status)]">
                {{ getStatusText(student.status) }}
                <span v-if="isOnline(student)" class="pulse-dot"></span>
              </span>
          </td>
        </tr>
        </tbody>
      </table>
      <div v-else class="empty-state">
        暂无学生连接数据
      </div>
    </div>
    <div v-else class="loading-state">
      加载中...
    </div>
  </div>
</template>

<script setup>
import {ref, computed, onMounted, onUnmounted} from 'vue';

const students = ref([]);
const isLoading = ref(false);
const error = ref(null);

// 计算属性：按最后心跳时间降序排序
const sortedStudents = computed(() => {
  return [...students.value].sort((a, b) => {
    const timeA = new Date(a.lastHeartbeat || 0).getTime();
    const timeB = new Date(b.lastHeartbeat || 0).getTime();
    return timeB - timeA;
  });
});

// 获取学生机器列表
const fetchStudents = async () => {
  try {
    // 直接使用完整后端地址
    const response = await fetch('http://localhost:8098/student/list');

    if (!response.ok) throw new Error(`HTTP错误: ${response.status}`);

    const data = await response.json();
    students.value = data;
  } catch (err) {
    console.error('请求失败:', err);
    error.value = `获取数据失败: ${err.message}`;
  }
};

// 检查是否在线
const isOnline = (student) => {
  return student.status === 'online' && student.isActive;
};

// 格式化日期
const formatDate = (date) => {
  if (!date) return '-';

  try {
    const dateObj = new Date(date);
    if (isNaN(dateObj.getTime())) return '-';

    // 显示为本地时间格式：YYYY-MM-DD HH:mm:ss
    return dateObj.toLocaleString('zh-CN', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
      hour12: false
    }).replace(/\//g, '-');
  } catch {
    return '-';
  }
};


// 获取状态文本
const getStatusText = (status) => {
  const statusMap = {
    'online': '在线',
    'offline': '离线',
    'submitted': '已交卷'
  };
  return statusMap[status] || status;
};

// 获取状态对应的CSS类
const getStatusClass = (status) => {
  const classMap = {
    'online': 'connected',
    'offline': 'disconnected',
    'submitted': 'submitted'
  };
  return classMap[status] || 'unknown';
};

// 组件挂载后获取数据
onMounted(() => {
  fetchStudents();

  // 每5秒刷新一次数据
  const intervalId = setInterval(fetchStudents, 5000);

  // 组件卸载时清除定时器
  onUnmounted(() => {
    clearInterval(intervalId);
  });
});
</script>

<style scoped>
.student-list {
  background: white;
  border-radius: 8px;
  padding: 1.5rem;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 1.5rem;
}

h2 {
  margin: 0;
  color: #2c3e50;
  font-size: 1.25rem;
  font-weight: 600;
}

.refresh-btn {
  padding: 0.5rem 1rem;
  background-color: #f0f2f5;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: all 0.2s;
}

.refresh-btn:hover {
  background-color: #e0e3e7;
}

.refresh-btn:disabled {
  opacity: 0.7;
  cursor: not-allowed;
}

.error-message {
  color: #f44336;
  background-color: #ffebee;
  padding: 0.75rem;
  border-radius: 4px;
  margin-bottom: 1rem;
}

.table-container {
  overflow-x: auto;
  border-radius: 6px;
  border: 1px solid #eee;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

th, td {
  padding: 0.75rem 1rem;
  text-align: left;
  border-bottom: 1px solid #eee;
}

th {
  background-color: #f8f9fa;
  font-weight: 600;
  color: #555;
  white-space: nowrap;
}

tr:hover td {
  background-color: #f5f7fa;
}

.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.75rem;
  border-radius: 12px;
  font-size: 0.8rem;
  font-weight: 500;
  white-space: nowrap;
}

.pulse-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background-color: currentColor;
  animation: pulse 1.5s infinite;
}

@keyframes pulse {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0.3;
  }
  100% {
    opacity: 1;
  }
}

.status-badge.connected {
  background-color: #e8f5e9;
  color: #2e7d32;
}

.status-badge.disconnected {
  background-color: #ffebee;
  color: #c62828;
}

.status-badge.submitted {
  background-color: #e3f2fd;
  color: #1565c0;
}

.empty-state, .loading-state {
  padding: 2rem;
  text-align: center;
  color: #666;
}

@media (max-width: 768px) {
  .student-list {
    padding: 1rem;
  }

  th, td {
    padding: 0.5rem;
  }
}
</style>